package net.hn.hnms.biz.power.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import net.hn.hnms.biz.api.feign.model.DataStateVo;
import net.hn.hnms.biz.common.jpa.utils.HqlUtils;
import net.hn.hnms.biz.common.jpa.utils.ResponsePage;
import net.hn.hnms.biz.power.domain.*;
import net.hn.hnms.biz.power.domain.dto.ChartDto;
import net.hn.hnms.biz.power.domain.dto.PointDto;
import net.hn.hnms.biz.power.domain.vo.ChartDateVo;
import net.hn.hnms.biz.power.mapper.GdjkSensormonitorHisMapper;
import net.hn.hnms.biz.power.repository.DeviceInfoRepository;
import net.hn.hnms.biz.power.repository.HisSensorMonitorRepository;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 智呈物联 pan'sx
 * 2022/9/21 10:41
 * 1.0 version
 */
@Service
@RequiredArgsConstructor
public class PowerServiceImpl implements PowerService {
    private final DeviceInfoRepository deviceInfoRepository;
    private final HisSensorMonitorRepository hisSensorMonitorRepository;
    private final JdbcTemplate jdbcTemplate;
    private final EntityManager entityManager;


    /**
     * 供电历史Mapper
     */
    @Resource
    private GdjkSensormonitorHisMapper gdjkSensormonitorHisMapper;

    @Override
    public List<DeviceInfo> currentData(String systemCode,String mineCode) {
        List<DeviceInfo> bySystemCodeOrderBySort;
        if(net.hn.hnms.sys.common.core.utils.StringUtils.isNotBlank(mineCode)){
            bySystemCodeOrderBySort=deviceInfoRepository.findBySystemCodeAndMineCodeOrderBySort(systemCode,mineCode);
        }else {
            bySystemCodeOrderBySort = deviceInfoRepository.findBySystemCodeOrderBySort(systemCode);
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.DAY_OF_MONTH,1);

        for (DeviceInfo deviceInfo : bySystemCodeOrderBySort) {
            List<SensorInfo> sensorInfos = deviceInfo.getSensorInfos();
            for (SensorInfo sensorInfo : sensorInfos) {
                if (sensorInfo.getSensorMonitor() != null) {
                    NowSensorMonitor sensorMonitor = sensorInfo.getSensorMonitor();
                    sensorInfo.setPointValueUnit(sensorMonitor.getPointValueUnit());
                    sensorInfo.setPointValue(sensorMonitor.getPointValue());
                    sensorInfo.setDataTime(sensorMonitor.getDataTime());
                    sensorInfo.setPointStatus(sensorMonitor.getPointStatus());
                    if(sensorInfo.getPointLocation().contains("电度")){
                        HisSensorMonitor monitor = hisSensorMonitorRepository.findFirstBySensorInfo_PointCodeAndDataTimeBeforeOrderByDataTimeDesc(sensorInfo.getPointCode(), calendar.getTime());
                        if(monitor!=null){
                            sensorInfo.setPointValue(sensorMonitor.getPointValue().subtract(monitor.getPointValue()));
                        }
                    }
                }
            }
        }
        return bySystemCodeOrderBySort;
    }

    @Override
    public List<Map<String, Object>> powerSelect(String mineCode) {
        if(StringUtils.isNotBlank(mineCode)){
            mineCode =" and mine_code='"+mineCode+"'";
        }else{
            mineCode="";
        }
        return jdbcTemplate.queryForList("SELECT distinct  system_code,install_location FROM \"dwd_gdjk_base_deviceinfo\" WHERE data_flag='0'"+mineCode);
    }

    @Override
    public ResponsePage<DeviceInfo> devPage(int pageNum, int pageSize, DeviceInfo deviceInfo) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotBlank(deviceInfo.getDeviceName())) {
            sb.append(" deviceName like '%").append(deviceInfo.getDeviceName()).append("%'");
            deviceInfo.setDeviceName(null);
        }
        PageRequest pageRequest = PageRequest.of(pageNum, pageSize);
        ResponsePage<DeviceInfo> page = HqlUtils.findPage(entityManager, deviceInfo,
                pageRequest, sb.toString(), Sort.by(Sort.Direction.ASC, "sort"));
        return page;
    }

    @Override
    public ResponsePage<NowSensorMonitor> sensormonitorPageList(int pageNum, int pageSize, NowSensorMonitor nowSensorMonitor) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotBlank(nowSensorMonitor.getDeviceType())) {
            sb.append(" and sensorInfo.deviceInfo.deviceType = '").append(nowSensorMonitor.getDeviceType()).append("'");
        }
//        if (StringUtils.isNotBlank(nowSensorMonitor.getTransformer())) {
//            sb.append(" and sensorInfo.deviceInfo.systemCode = '").append(nowSensorMonitor.getTransformer()).append("'");
//        }
        if (StringUtils.isNotBlank(nowSensorMonitor.getInstallLocation())) {
            sb.append(" and sensorInfo.deviceInfo.installLocation = '").append(nowSensorMonitor.getInstallLocation()).append("'");
        }
        if (StringUtils.isNotBlank(nowSensorMonitor.getDeviceCode())) {
            sb.append(" and sensorInfo.deviceInfo.deviceCode = '").append(nowSensorMonitor.getDeviceCode()).append("'");
        }
        if (StringUtils.isNotBlank(nowSensorMonitor.getDeviceName())) {
            sb.append(" and sensorInfo.deviceInfo.deviceName like '%").append(nowSensorMonitor.getDeviceName()).append("%' ");
        }
        PageRequest pageRequest = PageRequest.of(pageNum, pageSize);
        ResponsePage<NowSensorMonitor> page = HqlUtils.findPage(entityManager, nowSensorMonitor,
                pageRequest, sb.toString());
        List<NowSensorMonitor> pageData = page.getPageData();
        pageData.forEach(s -> {
            if (s.getSensorInfo() != null) {
                s.setPointLocation(s.getSensorInfo().getPointLocation());
                s.setPointTypeName(s.getSensorInfo().getPointTypeName());
                s.setPointTypeCode(s.getSensorInfo().getPointTypeCode());
                s.setDeviceCode(s.getSensorInfo().getDeviceInfo().getDeviceCode());
                s.setDeviceName(s.getSensorInfo().getDeviceInfo().getDeviceName());
                s.setPointCode(s.getSensorInfo().getPointCode());
                s.setPointValueUnit(s.getSensorInfo().getPointValueUnit());
            }
        });
        return page;
    }

    @Override
    public ResponsePage<HisSensorMonitor> hisSensormonitorPageList(int pageNum, int pageSize, HisSensorMonitor hisSensorMonitor) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotBlank(hisSensorMonitor.getDeviceType())) {
            sb.append(" and sensorInfo.deviceInfo.deviceType = '").append(hisSensorMonitor.getDeviceType()).append("'");
        }
        if (StringUtils.isNotBlank(hisSensorMonitor.getStartTime())) {
            sb.append(" and dataTime >='").append(hisSensorMonitor.getStartTime()).append("'");
        }
        if (StringUtils.isNotBlank(hisSensorMonitor.getEndTime())) {
            sb.append(" and dataTime <='").append(hisSensorMonitor.getEndTime()).append("'");
        }
        if (StringUtils.isNotBlank(hisSensorMonitor.getInstallLocation())) {
            sb.append(" and sensorInfo.deviceInfo.installLocation = '").append(hisSensorMonitor.getInstallLocation()).append("'");
        }
        if (StringUtils.isNotBlank(hisSensorMonitor.getDeviceCode())) {
            sb.append(" and sensorInfo.deviceInfo.deviceCode = '").append(hisSensorMonitor.getDeviceCode()).append("'");
        }
        if (StringUtils.isNotBlank(hisSensorMonitor.getDeviceName())) {
            sb.append(" and sensorInfo.deviceInfo.deviceName like '%").append(hisSensorMonitor.getDeviceName()).append("%' ");
        }
        PageRequest pageRequest = PageRequest.of(pageNum, pageSize);
        ResponsePage<HisSensorMonitor> page = HqlUtils.findPage(entityManager, hisSensorMonitor,
                pageRequest, sb.toString(), Sort.by(Sort.Direction.DESC, "dataTime"));
        List<HisSensorMonitor> pageData = page.getPageData();
        pageData.forEach(s -> {
            if (s.getSensorInfo() != null) {
                s.setPointLocation(s.getSensorInfo().getPointLocation());
                s.setPointTypeName(s.getSensorInfo().getPointTypeName());
                s.setPointTypeCode(s.getSensorInfo().getPointTypeCode());
                s.setDeviceCode(s.getSensorInfo().getDeviceInfo().getDeviceCode());
                s.setDeviceName(s.getSensorInfo().getDeviceInfo().getDeviceName());
                s.setPointCode(s.getSensorInfo().getPointCode());
                s.setPointValueUnit(s.getSensorInfo().getPointValueUnit());
            }
        });
        return page;
    }

    /**
     * 条件查询历史数据测点曲线
     * @param pointDto
     * @return
     */
    @Override
    public ChartDateVo pointHistoryCurve(PointDto pointDto) {
        //1天内 日期间隔不做处理
        //1~3天 日期间隔5分钟 取最大值
        //3天~1月  日期间隔1小时 取最大值
        //超过1月  返回前端消息，查询时间范围为一个月

        //查询得数据集合
        List<GdjkSensormonitorHisPo> gdjkSensormonitorHisPos = null;
        //返回得数据集合Vo
        ChartDateVo chartDateVo = new ChartDateVo();
        List<Date> dateList = new ArrayList<>();
        List<BigDecimal> bigDecimalList = new ArrayList<>();


        if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 1 * 1000L) {
            LambdaQueryWrapper<GdjkSensormonitorHisPo> queryWrapper = new LambdaQueryWrapper<>();
            //一天内得数据
            queryWrapper.ge(GdjkSensormonitorHisPo::getDataTime,pointDto.getStartTime());
            //结束时间
            queryWrapper.le(pointDto.getEndTime() != null, GdjkSensormonitorHisPo::getDataTime, pointDto.getEndTime());
            queryWrapper.eq(GdjkSensormonitorHisPo::getPointCode, pointDto.getPointCode());

            //煤矿编码
            queryWrapper.eq(net.hn.hnms.sys.common.core.utils.StringUtils.isNotEmpty(pointDto.getMineCode()),GdjkSensormonitorHisPo::getMineCode,pointDto.getMineCode());
            gdjkSensormonitorHisPos = gdjkSensormonitorHisMapper.selectList(queryWrapper);
        } else if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 3 * 1000L) {
            //三天内得数据
            List<ChartDto> chartDtoList= gdjkSensormonitorHisMapper.selectOneDayList(pointDto);
            for (ChartDto chartDto : chartDtoList) {
                dateList.add(chartDto.getTime());
                bigDecimalList.add(chartDto.getValue());
            }
            chartDateVo.setDate(dateList);
            chartDateVo.setValue(bigDecimalList);
            return chartDateVo;
        } else if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 31 * 1000L) {
            //1月内得数据
            List<ChartDto> chartDtoList= gdjkSensormonitorHisMapper.selectOneMonthList(pointDto);
            for (ChartDto chartDto : chartDtoList) {
                dateList.add(chartDto.getTime());
                bigDecimalList.add(chartDto.getValue());
            }
            chartDateVo.setDate(dateList);
            chartDateVo.setValue(bigDecimalList);
            return chartDateVo;
        }

        if (gdjkSensormonitorHisPos.isEmpty()) {

            chartDateVo.setDate(dateList);
            chartDateVo.setValue(bigDecimalList);
            return chartDateVo;
        }
        //list 降序排列
        List<GdjkSensormonitorHisPo> collect = gdjkSensormonitorHisPos.stream().sorted(Comparator.comparing(GdjkSensormonitorHisPo::getDataTime).reversed()).collect(Collectors.toList());
        for (GdjkSensormonitorHisPo gdjkSensormonitorHisPo : collect) {
            dateList.add(gdjkSensormonitorHisPo.getDataTime());
            bigDecimalList.add(gdjkSensormonitorHisPo.getPointValue());
        }
        chartDateVo.setDate(dateList);
        chartDateVo.setValue(bigDecimalList);
        return chartDateVo;
    }

    /**
     * 条件查询历史数据测点列表
     * @param pointDto
     * @return
     */
    @Override
    public List<PointHistoryListVo> pointHistoryList(PointDto pointDto) {
        //1天内 日期间隔不做处理
        //1~3天 日期间隔5分钟 取最大值
        //3天~1月  日期间隔1小时 取最大值
        //超过1月  返回前端消息，查询时间范围为一个月

        //查询得数据集合
        List<GdjkSensormonitorHisPo> gdjkSensormonitorHisPos = null;

        String stateCode = "1";

        if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 1 * 1000L) {
            LambdaQueryWrapper<GdjkSensormonitorHisPo> queryWrapper = new LambdaQueryWrapper<>();
            //一天内得数据
            queryWrapper.ge(GdjkSensormonitorHisPo::getDataTime,pointDto.getStartTime());
            //结束时间
            queryWrapper.le(pointDto.getEndTime() != null, GdjkSensormonitorHisPo::getDataTime, pointDto.getEndTime());
            queryWrapper.eq(GdjkSensormonitorHisPo::getPointCode, pointDto.getPointCode());

            //煤矿编码
            queryWrapper.eq(net.hn.hnms.sys.common.core.utils.StringUtils.isNotEmpty(pointDto.getMineCode()),GdjkSensormonitorHisPo::getMineCode,pointDto.getMineCode());
            gdjkSensormonitorHisPos = gdjkSensormonitorHisMapper.selectList(queryWrapper);
        } else if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 3 * 1000L) {
            //三天内得数据
            List<ChartDto> chartDtoList= gdjkSensormonitorHisMapper.selectOneDayList(pointDto);
            List<PointHistoryListVo> collect = chartDtoList.stream().map(t -> {
                PointHistoryListVo pointHistoryListVo = new PointHistoryListVo();
                pointHistoryListVo.setDate(t.getTime());
                pointHistoryListVo.setValue(t.getValue());
                pointHistoryListVo.setState(stateCode.equals(t.getState()) ? "正常" : "异常");
                pointHistoryListVo.setStateCode(t.getState());
                return pointHistoryListVo;
            }).collect(Collectors.toList());
            return collect;
        } else if (pointDto.getEndTime().getTime() - pointDto.getStartTime().getTime() <= 3600 * 24 * 31 * 1000L) {
            //1月内得数据
            List<ChartDto> chartDtoList= gdjkSensormonitorHisMapper.selectOneMonthList(pointDto);
            List<PointHistoryListVo> collect = chartDtoList.stream().map(t -> {
                PointHistoryListVo pointHistoryListVo = new PointHistoryListVo();
                pointHistoryListVo.setDate(t.getTime());
                pointHistoryListVo.setValue(t.getValue());
                pointHistoryListVo.setState(stateCode.equals(t.getState()) ? "正常" : "异常");
                pointHistoryListVo.setStateCode(t.getState());
                return pointHistoryListVo;
            }).collect(Collectors.toList());
            return collect;
        }

        if (gdjkSensormonitorHisPos.isEmpty()) {
            return new ArrayList<>();
        }
        //list 降序排列
        List<GdjkSensormonitorHisPo> collect = gdjkSensormonitorHisPos.stream().sorted(Comparator.comparing(GdjkSensormonitorHisPo::getDataTime).reversed()).collect(Collectors.toList());
        List<PointHistoryListVo> collectVo = collect.stream().map(t -> {
            PointHistoryListVo pointHistoryListVo = new PointHistoryListVo();
            pointHistoryListVo.setDate(t.getDataTime());
            pointHistoryListVo.setValue(t.getPointValue());
            pointHistoryListVo.setState(stateCode.equals(t.getPointStatus().toString()) ? "正常" : "异常");
            pointHistoryListVo.setStateCode(t.getPointStatus().toString());
            return pointHistoryListVo;
        }).collect(Collectors.toList());
        return collectVo;
    }

    @Override
    public List<DataStateVo> getMaxTime(String mineCode, String companyCode) {
        String sql="SELECT mine_code as mineCode,max(data_time) as maxTime  FROM dwd_gdjk_now_sensormonitor where 1=1 %s %s group by mine_code";
        if(StringUtils.isNotBlank(mineCode)){
            mineCode ="and mine_code='"+mineCode+"' ";
        }else{
            mineCode="";
        }
        if(StringUtils.isNotBlank(companyCode)&&StringUtils.isBlank(mineCode)){
            companyCode ="and company_code='"+companyCode+"' ";
        }else {
            companyCode="";
        }
        List<DataStateVo> query = jdbcTemplate.query(String.format(sql, mineCode, companyCode), new BeanPropertyRowMapper<>(DataStateVo.class));
        return query;
    }
}
